"use strict";

var router = require("router"),
    TokenService = require("router").TokenService,
    mongo = require('./core/mongoservice'),
    ObjectId = require('mongodb').ObjectID,
    Q = require('q');

function TagService() {
    console.log("TagService constructor");
}
TagService.prototype = Object.create(TokenService.prototype);
TagService.prototype.constructor = TagService;

TagService.prototype.insert = function (request, response, promise) {
    return promise.then(function (self) {
        //self.identify(request, response);
        return self.mongoSave(request.body).then(function (data) {
            return response.send({ request: request, content: data });
        });
    });
};

TagService.prototype.search = function (request, response, promise) {
    return promise.then(function (self) {

        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);
        var query = request.query.q;

        return self.mongoGetStartsWith(query, { skip: skip, limit: limit}).then(function (data) {
            return response.send({ request: request, content: data });
        });
    });
};

TagService.prototype.searchHashtag = function (request, response, promise) {
    return promise.then(function (self) {

        var skip = parseInt(request.query.skip);
        var limit = parseInt(request.query.limit);
        var query = request.query.q;

        return self.mongoGetHashtagStartsWith(query, { skip: skip, limit: limit}).then(function (data) {
            return response.send({ request: request, content: data });
        });
    });
};

/*-------------------------------------------------------*/
/*mongo daf*/

TagService.prototype.mongoInsert = function (tag) {
    if (!tag) throw new Error("tag is not defined.");
    if (tag._id) throw new Error("tag already has id: " + tag._id);
    var self = this;

    return mongo.insert('tags', tag).then(function (tags) {
        return require("./researchservice").mongoSave(tag.name).then(function () {
            return tags[0];
        });
    });
};

TagService.prototype.mongoSave = function (tag) {
    if (!tag) throw new Error("tag is not defined.");
    if (!tag.name) throw new Error("name is not defined.");
    var self = this;

    var query = tag.name;
    query = query.replace(' ', '\\s');
    var regex = new RegExp("^" + query + "$", "ig");

    return mongo.findOne('tags', { name: { $regex: regex} }).then(function (res) {
        if (res) return res;
        return self.mongoInsert(tag);
    });
};

TagService.prototype.mongoSaveTags = function (tags) {
    if (!tags) throw new Error("tags is not defined.");
    var self = this;

    var promises = [];
    tags.forEach(function (tag) {
        promises.push(self.mongoSave({name: tag})); //insert tag tb collection
    });
    return Q.all(promises).then(function () {
        return tags;
    });
};

TagService.prototype.mongoGetStartsWith = function (query, options) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    var opts = {};
    options = options || {}
    if (options.limit) opts.limit = options.limit;
    if (options.skip) opts.skip = options.skip;
    opts.sort = { "name": 1 };

    opts.limit = opts.limit || 20;

    query = query.replace(' ', '\\s');
    var regex = new RegExp("^" + query, "ig");

    return mongo.find('tags', { name: { $regex: regex} }, opts).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray');
    });
};

TagService.prototype.mongoGetHashtagStartsWith = function (query, options) {
    return this.mongoGetStartsWith(query, options).then(function (results) {
        return results.reduce(function (previous, current) {
            var hashtag = current.name.replace(/([\W\s])/gi, '');
            previous.push({
                _id: current._id,
                name: current.name,
                hashtag: hashtag
            });
            return previous;
        }, []);
    });
};

TagService.prototype.mongoSplitSearch = function (tags) {
    var self = this;
    console.log("mongoSplitSearch tags:", JSON.stringify(tags));
    return Q.fcall(function () {
        if (!tags) throw new Error("input is not defined.");

        var realTags = [];
        if (tags.length == 0) return realTags;

        var tag = tags[0];
        return self.mongoGetStartsWith(tag).then(function (results) {
            var skip = 1;
            console.log("mongoGetStartsWith(" + tag + ") => ", JSON.stringify(results));
            for (var i = 0; i < results.length; i++) {
                var result = results[i].name;
                var words = result.split(' ');
                console.log("split result.name: " + result + "  => ", JSON.stringify(words));
                if (words.length <= tags.length) {
                    var same = true;
                    for (var j = 0; j < words.length && same; j++) {
                        if (tags.length <= j) {
                            same == false;
                            break;
                        }
                        else {
                            console.log("compare word: ", words[j].toLowerCase(), " à tag: ", tags[j].toLowerCase());
                            same = words[j].toLowerCase() == tags[j].toLowerCase();
                            if (!same) break;
                        }
                    }
                    if (same) {
                        console.log("push", result, " in realTags");
                        realTags.push(result);
                        skip = j;
                        break;
                    }
                }
            }
            if (realTags.length == 0) {
                console.log("push", result, "in realTags (single word)");
                realTags.push(tag);
            }
            console.log("before splice", JSON.stringify(tags));
            tags.splice(0, skip);
            console.log("tags after splice", JSON.stringify(tags));
            return self.mongoSplitSearch(tags).then(function (tags) {
                tags.forEach(function (tag) {
                    realTags.push(tag);
                });

                return realTags;
            });
        });
    });
};

TagService.prototype.mongoSplit = function (query) {
    if (!query) throw new Error("query is not defined.");
    var self = this;

    return Q.fcall(function () {
        var tokens = query.split(/[\s,;]+/g);
        return self.mongoSplitSearch(tokens);
    });
};

/*-------------------------------------------------------*/
/*common*/

TagService.prototype.extractHashtag = function (content) {
    var self = this;

    return Q.fcall(function () {
        content = content || "";

        var re = /(#)([\w|áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ\']+)/gi;

        var res = null;
        var tags = [];
        while ((res = re.exec(content)) != null) {
            var camelCase = res[2];
            var words = camelCase.split(/(?=[A-Z])/).join(' ');
            words = words.toLowerCase();

            tags.push(words);
        }
        return {
            tags: tags
        }
    });
};

exports = module.exports = new TagService();